﻿
using System;
using System.Collections.Generic;
//using Unity.Android.Gradle.Manifest;
using UnityEngine;

public class UIService : ILogic
{
   // private Camera uiCamera;
    private Transform uiRoot;
    private Dictionary<string,WindowBase> allWindowDic = new Dictionary<string,WindowBase>();   
    private List<WindowBase> allVisibleWindowList = new List<WindowBase>();
    public void OnInit()
    {
        var target = GameObject.Find("UIRoot");
        if (target == null)
        {
            uiRoot = new GameObject("UIRoot").transform;
            uiRoot.parent = GameRoot.Instance.transform;
        }
        else
        {
            uiRoot = target.transform;
        }
    }

    public void UnInit()
    {
        
    }
    public void OnUpdate()
    {
        for (int i = 0; i < allVisibleWindowList.Count; i++)
        {
            allVisibleWindowList[i].OnUpdate();
        }
    }

    #region 打开窗口
    public T PopWindow<T>(Transform parent = null) where T : WindowBase, new()
    {
        Transform root = null;
        string name = typeof(T).Name;
        if (allWindowDic.TryGetValue(name, out var window))
        {
            return ShowWindow(name) as T;
        }
        else
        {
            window = new T();
            if (parent == null)
            {
                root = uiRoot;
            }
            else
            {
                root = parent;
            }
            return InitWindow(window, name, root) as T;
        }
    }
    //提供一个编译不可知类型但能动态加载窗口的API
    public WindowBase PopWindow(Type windowType) 
    {
        string name = windowType.Name;
        if (allWindowDic.TryGetValue(name, out var window))
        {
            return ShowWindow(name) ;
        }
        else
        {
            window = (WindowBase)Activator.CreateInstance(windowType);
            this.LogRed("UI根节点为"+uiRoot);
           
            if (window != null)
            {
                return InitWindow(window, name,uiRoot);
            }
            this.Error($"{windowType.Name}无法创建实例对象");
            return null;
        }
    }

    private WindowBase ShowWindow(string name)
    {
        if (allWindowDic.TryGetValue(name, out var window))
        {
            if (!allVisibleWindowList.Contains(window))
            {
                window.SetVisible(true);

                window.OnShow();
                allVisibleWindowList.Add(window);
               // HindMorePopWindow(window);
                return window;
            }
            else
            {
                //this.Warn($"{name}已经打开了");
                return window;
            }
        }
        else
        {
            this.Error($"{name}不在allWindowDic内");
            return null;
        }
    }

    private WindowBase InitWindow(WindowBase window,string windowName,Transform parent)
    {
        GameObject windowPrefab = null;
        windowPrefab = LoadWindow(windowName,parent);
        //绑定预制体
        window.gameObject = windowPrefab;
        window.transform = windowPrefab.transform;
        window.canvas = windowPrefab.GetComponent<Canvas>();
        //设置脚本参数   
        window.Name = windowName;
       // window.canvas.worldCamera = uiCamera;
        SetWindowLayer(window.canvas.sortingOrder, window);
        window.SetVisible(true);
        //初始化脚本
        window.OnAwake();
        window.OnShow();
        //更新数据结构
        allWindowDic.Add(windowName, window);
        allVisibleWindowList.Add(window);
        //自动关闭多余的弹窗
       // HindMorePopWindow(window);
        return window;
    }
    private void SetWindowLayer(int SOrder,WindowBase windowBase)
    {
        if (SOrder < 100)
        {
            windowBase.windowLayer = WindowLayer.Base;
        }
        else if (SOrder >= 100 && SOrder < 200)
        {
            windowBase.windowLayer = WindowLayer.Pop;
        }
        else
        {
            windowBase.windowLayer = WindowLayer.Top;
        }
    }
    private GameObject LoadWindow(string windowName,Transform parent)
    {
        GameObject go = null;
        string path = "";
        //初始化预制体：
        if (windowName.Contains("Window") ||windowName.Contains("Icon"))
        {
            path = $"UIWindow/{windowName}";
        }
        else if(windowName.Contains("Comp"))
        {
            path = $"UIWindow/Comp/{windowName}";
        }
        go = GameObject.Instantiate(Resources.Load<GameObject>(path), parent, false);

        if (go == null)
        {
            this.Error($"{windowName}没有在路径UIWindow/{windowName}下找到");
            return null;
        }
        go.transform.localPosition = Vector3.zero;
        go.transform.localRotation = Quaternion.identity;
        go.transform.localScale = Vector3.one;
        go.SetActive(false);
        return go;
    }
    #endregion

    #region 获取窗口
    public T GetActiveWindow<T>() where T: WindowBase
    {
        string name = typeof(T).Name;
        WindowBase window = GetWindow(name);
        if (window != null&&window.isVisible)
        {
            return window as T;
        }
        return null;
    }
    public T GetWindow<T>() where T : WindowBase
    {
        string name = typeof(T).Name;
        WindowBase window = GetWindow(name);
        if (window != null)
        {
            return window as T;
        }
        return null;
    }
    //获取所有在字典窗口
    public WindowBase GetWindow(string windowName)
    {
        if (allWindowDic.TryGetValue(windowName, out var window))
        {
            if (window != null)
            {
                return window;
            }
        }
        return null;
    }
    #endregion

    #region 掩藏窗口
    public void HideWindow<T>()
    {
        string name = typeof (T).Name;
        HideWindow(name);
    }
    public void HideWindow(string name)
    {
        WindowBase window = GetWindow(name);
        if (window == null)
        {
            this.Error($"{name}不存在或者已经被销毁");
            return;
        }
        if (window.isVisible)
        {
            window.OnHide();
            window.SetVisible(false);
            allVisibleWindowList.Remove(window);
        }
        else
        {
            this.Warn($"{name}已经掩藏或者关闭");
        }
    }
    #endregion

    #region 打开&&关闭窗口

    public T PopOrHideWindow<T>(Transform parent =null)where T : WindowBase,new ()
    {
        Transform root = null;
        string name = typeof(T).Name;
        if (allWindowDic.TryGetValue(name, out var window))
        {
            if (!window.isVisible)
            {
                return ShowWindow(name) as T;
            }
            else
            {
                HideWindow(name);
                return null;
            }
        }
        else
        {
            T wind =new T();
            if (parent == null)
            {
                root = uiRoot;
            }
            else
            {
                root = parent;
            }
            return InitWindow(wind, name, root) as T;
        } 

    }
    #endregion

    #region 加载窗口
    //LoadingWindow window = null;
    //public void UpdateLoadingProgress(float progress)
    //{
    //    if (window == null || window.isVisible == false)
    //    {
    //        window = PlayWindowAnimation<LoadingWindow>();
    //    }
    //}
    //public void HideLoadingWindow()
    //{
    //    //延迟加载窗口的关闭时间
    //    GameRoot.Instance.timerService.AddTask(500, GetWindow<LoadingWindow>().HideLoadingWindow);
    //}
    #endregion
   
    #region 销毁窗口
    public void DestroyWindow<T>()
    {
        string name = typeof(T).Name;
        DestroyWindow(name);
    }
    public void DestroyWindow(string name)
    {
        WindowBase window = GetWindow(name);
        if (window!=null&&window.gameObject != null)
        {
            window.OnHide();
            window.OnDestroy();
            GameObject.Destroy(window.gameObject);
            allWindowDic.Remove(name);
            allVisibleWindowList.Remove(window);
        }
        else
        {
            this.Error($"{name}的GameObject不存在");
        }
    }

    #endregion

    #region 批量隐藏
    public void HideWindowLayer(WindowLayer windowLayer, List<WindowBase> filterList = null)
    {
        List<WindowBase> windowToHide = new List<WindowBase>();
        foreach (var window in allVisibleWindowList)
        {
            if (window.windowLayer == windowLayer)
            {
                if (filterList != null && filterList.Count > 0 && filterList.Contains(window))
                {
                    continue;
                }
                windowToHide.Add(window);
            }
        }
        foreach (var window in windowToHide)
        {
            HideWindow(window.Name);
        }
    }
    #endregion

    #region 批量销毁

    public void DestroyWindowLayer(WindowLayer windowLayer, List<WindowBase> filterList = null)
    {
        List<WindowBase> windowToDestroy = new List<WindowBase>();
        foreach (var window in allWindowDic.Values)
        {
            if (window.windowLayer == windowLayer)
            {
                if (filterList != null && filterList.Count > 0&& filterList.Contains(window))
                {
                    continue;
                }
                windowToDestroy.Add(window);
                //遍历字典时移除字典元素是不安全的，需要写一个临时删除的列表
            }
        }
        foreach (var window in windowToDestroy)
        {
            this.Log(window.Name + "被销毁");
            DestroyWindow(window.Name);
        }
        //在循环一遍字典，避免它的父销毁了，但是子还在字典中
        foreach (var comp in allWindowDic)
        {
            if (comp.Value.gameObject==null)
            {
                allWindowDic.Remove(comp.Key);
            }
        }
    }
    #endregion

    #region 切换基础层UI
    string lastWindowName ="";
    public void SwitchBaseLayerUI(GameObject window)
    {
        if (window == null)
        {
            SwitchBaseLayerUI("");
            return;
        }
        //UIWindow的初始化
        SwitchBaseLayerUI(window.name);
    }
    public void SwitchBaseLayerUI(string targetWindowName)
    {
        if (targetWindowName == string.Empty)
        {
            DestroyWindowLayer(WindowLayer.Base);
            DestroyWindowLayer(WindowLayer.Pop);
            return;
        }
        if (lastWindowName == targetWindowName)
        {
            HideWindow(targetWindowName);
            PopWindow(Type.GetType(targetWindowName));
            return;
        }
        lastWindowName = targetWindowName;
        //删除存在的基础层和Pop层UI
        DestroyWindowLayer(WindowLayer.Base);
        DestroyWindowLayer(WindowLayer.Pop);

        if (targetWindowName == string.Empty|| targetWindowName==null) 
        { 
            this.Warn(targetWindowName + "不存在或者没有设置场景Base窗口"); return;
        }
        Type type = Type.GetType(targetWindowName);
        if (type == null)
        {
            this.Warn(targetWindowName + "不存在或者没有设置场景Base窗口" );
            return;
        }
        //显示新场景的UI      
        PopWindow(type);
    }
   

    #endregion
    //每次打开Pop窗口时调用
    private void HindMorePopWindow(WindowBase targetWindow)
    {
        List<WindowBase> windowBases = new List<WindowBase>();
        windowBases.AddRange(allVisibleWindowList);
        if (targetWindow.windowLayer != WindowLayer.Pop)
        {
            return;
        }
        foreach (var window in windowBases)
        {
            if (window.windowLayer != WindowLayer.Pop)
            {
                continue;
            }
            if (window.Name == targetWindow.Name)
            {
                continue;
            }
            if (window.canvas.sortingOrder < targetWindow.canvas.sortingOrder)
            {
                HideWindow(window.Name);
            }
        }
    }

    public void OnEnterState()
    {
        
    }

    public bool IsActive<T>() where T: WindowBase
    {
        string window = typeof(T).Name;
        if (!allWindowDic.TryGetValue(window, out var windowBase))
        {
            return false;
        }
        if (allVisibleWindowList.Contains(windowBase))
        {
            return true;
        }
        return false;
    }

    //TODO 预加载系统

    //TODO 队列弹窗和关闭系统

    #region 提示弹窗
    //public void ShowTipWindow(string tips)
    //{
    //  PlayWindowAnimation<TipWindow>().ShowTip(tips);
    //}
    #endregion

}